package com.loong.common.mybatis.business;


import com.github.pagehelper.ISelect;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.loong.common.mybatis.entity.BaseEntity;
import com.loong.common.mybatis.mapper.Mapper;
import com.loong.common.domain.BaseQuery;
import com.loong.common.domain.Pager;
import com.loong.common.exception.GlobalException;
import com.loong.common.mybatis.tools.PageTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ReflectionUtils;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;

@Slf4j
public class AbstractBusiness<T extends BaseEntity> implements IBusiness<T> {

    @Autowired
    protected Mapper<T> mapper;

    /**
     * 当前泛型真实类型的Class
     */
    private Class<T> modelClass;

    @SuppressWarnings("unchecked")
	public AbstractBusiness() {
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        modelClass = (Class<T>) pt.getActualTypeArguments()[0];
    }

    @Override
    public void save(T model) {
        mapper.insertSelective(model);
    }

    @Override
    public void save(List<T> models) {
        mapper.insertList(models);
    }

    @Override
    public void deleteById(Object id) {
        mapper.deleteByPrimaryKey(id);
    }
    @Override
    public void softDeleteById(Object id)  {
        Condition condition = new Condition(modelClass);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("id",id);
        softDelete(condition);
    }

    private void softDelete(Condition condition) {
        T t = null;
        try {
            t = modelClass.newInstance();
            t.setDeleted(true);
            mapper.updateByConditionSelective(t, condition);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void softDeleteByIds(List<Long> ids)  {
        Condition condition = new Condition(modelClass);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andIn("id",ids);
        softDelete(condition);
    }

    @Override
    public void deleteByIds(String ids) {
        mapper.deleteByIds(ids);
    }

    @Override
    public void deleteByCondition(Condition condition) {
        mapper.deleteByCondition(condition);
    }

    @Override
    public void updateByPrimaryKeySelective(T model) {
        mapper.updateByPrimaryKeySelective(model);
    }


    @Override
    public void updateByPrimaryKey(T model) {
        mapper.updateByPrimaryKey(model);
    }

    @Override
    public T findById(Object id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public T findBy(String fieldName, Object value) throws GlobalException {
        try {
            T model = modelClass.newInstance();
            Field field = ReflectionUtils.findField(modelClass,fieldName);
            field.setAccessible(true);
            field.set(model, value);
            return mapper.selectOne(model);
        } catch (ReflectiveOperationException e) {
            throw new GlobalException(e.getMessage(), e);
        }
    }

    @Override
    public List<T> findAllBy(String fieldName, Object value) throws GlobalException {
        try {
            T model = modelClass.newInstance();
            Field field = modelClass.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(model, value);
            return mapper.select(model);
        } catch (ReflectiveOperationException e) {
            throw new GlobalException(e.getMessage(), e);
        }
    }

    @Override
    public List<T> findByIds(String ids) {
        return mapper.selectByIds(ids);
    }

    @Override
    public List<T> findByCondition(Condition condition) {
        return mapper.selectByCondition(condition);
    }

    @Override
    public List<T> findAll() {
        return mapper.selectAll();
    }

    @Override
    public T selectOne(T param) {
        return mapper.selectOne(param);
    }

    @Override
    public List<T> selectAll(T param) {
        return mapper.select(param);
    }

    @Override
    public List<T> selectByProperties(T param) {
        Field[] declaredFields = modelClass.getDeclaredFields();
        Condition condition = new Condition(modelClass);
        Example.Criteria criteria = condition.createCriteria();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            try {
                Object o = declaredField.get(param);
                if(ObjectUtils.isNotEmpty(o)){
                    criteria.andEqualTo(declaredField.getName(),o);
                }
            } catch (IllegalAccessException e) {
                log.error("reflect error:{}",e);
            }
        }
        return mapper.selectByCondition(condition);
    }

    @Override
    public Pager<T> pageQuery(BaseQuery baseQuery, ISelect iSelect) {
       return PageTools.pageQuery(baseQuery,iSelect);
    }
    @Override
    public Long count(ISelect iSelect){
        return PageHelper.count(iSelect);
    }


}
